home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Documentation / DirectX9 / directx9_m.chm / directx / code / common.js < prev    next >
Encoding:
JavaScript  |  2004-09-30  |  26.0 KB  |  891 lines

  1. //return the persistence wrapper
  2. function EnsurePersistence()
  3. {
  4.   if (typeof(EnsurePersistence.oPersistence) == 'object')
  5.   {
  6.     return EnsurePersistence.oPersistence;
  7.   }
  8.   else
  9.   {
  10.     EnsurePersistence.oPersistence = new CPersistence();
  11.     return EnsurePersistence.oPersistence;
  12.   }
  13. }
  14.  
  15. //Constructor for the persistence object
  16. function CPersistence()
  17. {
  18.   this.bXMLDocLoadedFlag=false;         //Indicates if the XML Document has been loaded yet.
  19.   this.bEnabled = false;            //Indicates that the browser supports the persistent feature
  20.   this.sPersistedMember;              //The current selection from of the members drop down
  21.   this.sStoreName="INETSDKStore";         //The name of the persistent data store
  22.   this.sSectionPath="";             //The path to the section objects in the XML doc
  23.   this.sMemberPath="";              //The path to the members object in the XML doc
  24.   var oHost=document.all.tags("H1").item(0);    //JSK: appendChild is not supported in IE4. Moved persistence to an element knonw to exist on the page.
  25.   this._oHostElem = oHost; // cache ref to element that hosts userdata behavior
  26. }
  27.  
  28. //Persists the users choice of a show/hide section
  29. CPersistence.prototype.persistSection = function(oSection, sText, sShowHide)
  30. {
  31.   if (this.bEnabled)
  32.   {
  33.     var oSectionNode = this.getObject(this.XMLDoc,this.sSectionPath + oSection.id);
  34.     var bSave = false;
  35.     if (sShowHide == "show" && oSectionNode == null)
  36.     {
  37.       oSectionNode=this.insertObject(this.XMLDoc,this.sSectionPath + oSection.id);
  38.       if (oSectionNode)
  39.       {
  40.         oSectionNode.setAttribute("sValue",sText);
  41.         bSave = true;
  42.       }
  43.     }
  44.     else if (sShowHide == "hide" && oSectionNode != null)
  45.     {
  46.       if (this.removeObject(this.XMLDoc,this.sSectionPath + oSection.id))
  47.         bSave = true;
  48.     }
  49.  
  50.     if (bSave)
  51.       this._oHostElem.save(this.sStoreName);
  52.   }
  53. }
  54.  
  55. //Persists what text should be highlited in example code
  56. CPersistence.prototype.persistHilite = function(oCode, sToken, oSample)
  57. {
  58.   if (this.bEnabled)
  59.   {
  60.     var oSectionNode=this.getObject(this.XMLDoc,this.sSectionPath + oSample.id);
  61.     if (oSectionNode!=null)
  62.     {
  63.       oSectionNode.setAttribute("sToken",sToken);
  64.       oSectionNode.setAttribute("sCode",oCode.id);
  65.       this._oHostElem.save(this.sStoreName);
  66.     }
  67.   }
  68. }
  69.  
  70. //Persists the user's selection from the members drop down
  71. CPersistence.prototype.persistMembers = function(sSelection)
  72. {
  73.   // Persist the current filter
  74.   if (this.bEnabled)
  75.   {
  76.     var oMemberNode=this.getObject(this.XMLDoc,this.sMemberPath);
  77.     if (oMemberNode == null)
  78.     {
  79.       oMemberNode=this.insertObject(this.XMLDoc,this.sMemberPath);
  80.     }
  81.     if (oMemberNode != null)
  82.     {
  83.       oMemberNode.setAttribute("sValue",sSelection);
  84.       this._oHostElem.save(this.sStoreName);
  85.       this.sPersistedMember=sSelection
  86.     }
  87.   }
  88. }
  89.  
  90. //Returns the user's last selection from the members drop down
  91. CPersistence.prototype.getPersistedMembers = function()
  92. {
  93.   this.LoadXML();
  94.   if (this.bEnabled)
  95.   {
  96.     if (!this.sPersistedMember)
  97.     {
  98.       var oNode=this.getObject(this.XMLDoc,this.sMemberPath);
  99.       if (oNode != null)
  100.       {
  101.         this.sPersistedMember=oNode.getAttribute("sValue");
  102.       }
  103.     }
  104.     return this.sPersistedMember;
  105.   }
  106.   else
  107.   {
  108.     return null;
  109.   }
  110. }
  111.  
  112. //Expands a section that has been stored.
  113. CPersistence.prototype.getPersistedSection = function(oElem, sCaption)
  114. {
  115.   this.LoadXML();
  116.   if (this.bEnabled)
  117.   {
  118.     var oSectionNode = this.getObject(this.XMLDoc,this.sSectionPath + oElem.id);
  119.     if (oSectionNode != null)
  120.     {
  121.       sCaption=oSectionNode.getAttribute("sValue");
  122.       ShowHideSection(oElem,sCaption);
  123.       if (oSectionNode.getAttribute("sToken") && oSectionNode.getAttribute("sCode"))
  124.       {
  125.         HiliteText(document.all(oSectionNode.getAttribute("sCode")), oSectionNode.getAttribute("sToken"));
  126.       }
  127.     }
  128.   }
  129. }
  130.  
  131. var gRegBS = new RegExp("[\\\\]", "g");
  132. function JustFName(sPath)
  133. {
  134.   sPath = sPath.replace(gRegBS, "/")
  135.   return sPath.substring(sPath.lastIndexOf("/")+1).split('.')[0]
  136. }
  137.  
  138.  
  139. //Initialization routine for most of the object properties
  140. //Provides TWO pieces of functionality.
  141. //Loads the persistent XML document if needed.
  142. //Determines if this is a post beta1 build.
  143. CPersistence.prototype.LoadXML = function()
  144. {
  145.   if (!this.bXMLDocLoadedFlag)
  146.   {
  147.     this.bXMLDocLoadedFlag=true;  //set flag regardless to prevent repeated initialization
  148.     this.bEnabled = (oBD.browser == "MSIE" && oBD.majorVer == 5);
  149.     if (this.bEnabled)
  150.     {
  151.       this._oHostElem.addBehavior("#default#userData");
  152.       var sLoad = "try { this._oHostElem.load(this.sStoreName); } catch(e) { this.bEnabled = false; }";
  153.       eval(sLoad); // protect <= JScript 3 from try/catch
  154.  
  155.       if (!this.bEnabled)
  156.         return;
  157.  
  158.       if (!this._oHostElem.XMLDocument)
  159.       {
  160.         this._oHostElem.save(this.sStoreName);
  161.       }
  162.       this.XMLDoc=this._oHostElem.XMLDocument;
  163.       var oRegBadXMLChars = new RegExp("[~]", "g"); // strip chars that are illegal for XML node names
  164.       var sFName = JustFName(document.location.pathname).replace(oRegBadXMLChars, "").toLowerCase();
  165.       this.sSectionPath= sFName + "/sections/";
  166.       this.sMemberPath= sFName + "/members";
  167.     }
  168.   }
  169.  
  170.   return;
  171. }
  172.  
  173. //Takes a path, converts to lowercase, strips leading slash and creates an array.
  174. //Assumes "/" character is the delimiter.
  175. var gRegLS = new RegExp("^[/]")
  176. CPersistence.prototype.getObjectHierarchy = function(sPath)
  177. {
  178.   sPath=sPath.replace(gRegLS, "");
  179.   return sPath.split("/");
  180. }
  181.  
  182. //Returns the XML object at the position in the document indicated by sPath.
  183. CPersistence.prototype.getObject = function(docObject, sPath)
  184. {
  185.   return docObject.documentElement.selectSingleNode(sPath);
  186. }
  187.  
  188. //Inserts an object in the XML document indicated by sPath
  189. CPersistence.prototype.insertObject = function(docObject, sPath)
  190. {
  191.   var aHierarchy = this.getObjectHierarchy(sPath);
  192.   var oCurNode=docObject.documentElement;
  193.   var iDepth = 0;
  194.   var bFound=false;
  195.   while (iDepth<aHierarchy.length)
  196.   {
  197.     bFound=false;
  198.     for (var i=0;i<oCurNode.childNodes.length;i++)
  199.     {
  200.       if (oCurNode.childNodes.item(i).nodeName==aHierarchy[iDepth])
  201.       {
  202.         oCurNode=oCurNode.childNodes.item(i);
  203.         bFound=true;
  204.         break;
  205.       }
  206.     }
  207.     if (!bFound)
  208.     {
  209.       var newNode=docObject.createElement(aHierarchy[iDepth])
  210.       oCurNode.insertBefore(newNode,null);
  211.       oCurNode=newNode;
  212.     }
  213.     iDepth++;
  214.   }
  215.   return oCurNode;
  216. }
  217.  
  218. //Removes the object from the XML document indicated by sPath.
  219. //If the removal of the object causes the parent to have no children then the parent is also removed.
  220. //This process continues recursively up to the but not including the docuement root
  221. CPersistence.prototype.removeObject = function(docObject, sPath)
  222. {
  223.   var oCurNode=this.getObject(docObject,sPath);
  224.   if (oCurNode==null)
  225.     return false;
  226.   var oParent=oCurNode.parentNode;
  227.   oParent.removeChild(oCurNode);
  228.   while (oParent.childNodes.length==0 && oParent != docObject.documentElement)
  229.   {
  230.     oCurNode=oParent;
  231.     oParent=oCurNode.parentNode;
  232.     oParent.removeChild(oCurNode);
  233.   }
  234.   return true;
  235. }
  236.  
  237. // Hilites the text in the code sample
  238. // oStart - reference to start of block
  239. // sText - string to find and hilite
  240. function HiliteText(oStart, sText)
  241. {
  242.   if (!oBD.getsNavBar)
  243.   {
  244.     // IE4/Mac doesn't support text ranges
  245.     return false;
  246.   }
  247.  
  248.   var oRng = document.body.createTextRange();
  249.   oRng.moveToElementText(oStart);
  250.   var oRngFixed = oRng.duplicate();
  251.  
  252.   if (typeof(HiliteText.tokens) == 'undefined')
  253.   {
  254.     HiliteText.tokens = new Array(1);
  255.   }
  256.   else
  257.   {
  258.     for (i = 0; i < HiliteText.tokens.length; i++)
  259.     {
  260.       if (HiliteText.tokens[i].m_sSectionID == oStart.id && HiliteText.tokens[i].m_sToken == sText)
  261.       {
  262.         return true;
  263.       }
  264.     }
  265.  
  266.     HiliteText.tokens.length++;
  267.   }
  268.  
  269.  
  270.   while (oRng.findText(sText, 1000000, 6) && oRngFixed.inRange(oRng))
  271.   {
  272.     oRng.execCommand('bold');
  273.     oRng.collapse(false);
  274.   }
  275.  
  276.   HiliteText.tokens[HiliteText.tokens.length-1] = new CHilitedToken(oStart.id, sText);
  277.  
  278.   return true;
  279. }
  280.  
  281. // a tuple representing the id of the section and the token to be hilited
  282. // the object is stored in an array to prevent the code from running twice on the same section
  283. function CHilitedToken(sSectionID, sToken)
  284. {
  285.   this.m_sSectionID = sSectionID;
  286.   this.m_sToken = sToken;
  287. }
  288.  
  289.  
  290. // Toggles the display of the content contained within oCode
  291. // oCode - reference to code block
  292. // sToken - string to bolden
  293. function ToggleSample(oCode, sToken)
  294. {
  295.   if (ShowHideSection(window.event.srcElement, 'Sample Code'))
  296.   {
  297.     HiliteText(oCode, sToken);
  298.     var oPersistence = EnsurePersistence();
  299.     oPersistence.persistHilite(oCode, sToken, window.event.srcElement);
  300.   }
  301. }
  302.  
  303. // If hidden, show. If shown, hide. Modify the caption of the element appropriately
  304. // Returns true if showing on return, false if hidden on return
  305. function ShowHideSection(oHead, sText)
  306. {
  307.   var bRet = false;
  308.   var oChild = document.all(oHead.getAttribute('child', false));
  309.  
  310.   if (typeof(oChild) == null)
  311.   {
  312.     return bRet;
  313.   }
  314.  
  315.   var sClass = oChild.className;
  316.   var sAction = "Show";
  317.   if (sClass == "clsCollapsed")
  318.   {
  319.     sAction = "Hide";
  320.     bRet = true; // we'll be showing upon return, so return true
  321.     var oPersistence = EnsurePersistence();
  322.     oPersistence.persistSection(oHead, sText, "show")
  323.   }
  324.   else
  325.   {
  326.     var oPersistence = EnsurePersistence();
  327.     oPersistence.persistSection(oHead, sText, "hide")
  328.   }
  329.   sAction = sAction + ' ' + sText;
  330.   oChild.className = (sClass == "clsCollapsed" ? "clsExpanded" : "clsCollapsed");
  331.   oHead.innerText = sAction;
  332.   return bRet;
  333. }
  334.  
  335. // Set the caption of the specified element
  336. // oElem - reference to element to modify. Typically a Hn
  337. // sCaption - New caption for the element
  338. // bShow - boolean indicating whether or not the element should be made visible
  339. function SetExpandableCaption(oElem, sCaption, bShow)
  340. {
  341.   oElem.innerText = sCaption;
  342.   if (bShow) oElem.style.display = 'inline';
  343.   var oPersistence = EnsurePersistence();
  344.   oPersistence.getPersistedSection(oElem, sCaption);
  345. }
  346.  
  347. function CheckCAB(n)
  348. {
  349.   return true;
  350. }
  351.  
  352. // Perform universal document post-processing at load time.
  353. function PostGBInit()
  354. {
  355.   if (oBD.getsNavBar)
  356.   {
  357.     if ("function" == typeof(CommonLoad)) CommonLoad();
  358.  
  359.     DecorateSnippets();
  360.  
  361.     if ('object' == typeof(oATTable) && 'object' == typeof(oATC) && 'function' == typeof(fnATInit))
  362.     {
  363.       fnATInit();
  364.     }
  365.  
  366.     //at EmitStandardsGlyphs();  removed cause it doesn't resolve at runtime in legacy asp.
  367.  
  368.     if ('object' == typeof(_topicdata) && 5<=oBD.majorVer) SetTopicData();
  369.   }
  370. }
  371.  
  372. // Decorate the contents of specially designated (AUTOHILITE) PREs
  373. function DecorateSnippets()
  374. {
  375.   if (oBD.majorVer<5) // behaviors are an IE5 thing
  376.   {
  377.     return;
  378.   }
  379.  
  380.   // if the global holding the location of our behavior is missing, we're sunk...
  381.   if (typeof(gsCodeDecoPath) != 'string')
  382.   {
  383.     return;
  384.   }
  385.  
  386.   // we know there's at least one DIV on the page, so attach it to the first one, and
  387.   // let the behavior do the walking so we don't have to instantiate multiple instances of a run-once behavior
  388.   var oDIVs = document.all.tags("DIV");
  389.   if (0 == oDIVs.length)
  390.   {
  391.     return;
  392.   }
  393.   var oDIV = oDIVs[0];
  394.  
  395.   // set properties on the DIV so that the hilite behavior will know the topic's name and persistent name
  396.   var sTopicName, sPN;
  397.   var oPD = EnsurePageData();
  398.   if (oPD && oPD.IsRefTopic())
  399.   {
  400.     if (sTopicName = oPD.GetTopicName())
  401.     {
  402.       oDIV.setAttribute("TOPICNAME", sTopicName);
  403.     }
  404.  
  405.     if (sPN = oPD.GetPersistentName())
  406.     {
  407.       oDIV.setAttribute("PERSISTENTNAME", sPN);
  408.     }
  409.   }
  410.  
  411.   oDIV.addBehavior(gsCodeDecoPath);
  412. }
  413.  
  414. // Encapsulates data about the page
  415. function CPageData()
  416. {
  417.   // contains all the reference pagetypes
  418.   this._oRegRef = new RegExp("(ref|const|struct|iface|isv_element|enum|function|object|method|pi|property|attribute|pseudo_class|pseudo_element|declaration|rule|event|collection|behavior|srcdisp|class|dhfilter|dhfilter_property|winmsg|dhcmdid)");
  419.  
  420.   if (typeof(_topicdata) == 'object')
  421.   {
  422.     this._sTopicName = _topicdata.getAttribute("name");
  423.     this._sPN = _topicdata.getAttribute("pn");
  424.  
  425.     this._sLocation = _topicdata.getAttribute("pubpath");
  426.     if (!this._sLocation)
  427.     {
  428.       this._sLocation = window.document.location.pathName;
  429.     }
  430.   }
  431.  
  432.   this._bRefTopic = false;
  433.   if (typeof(pagetype) == 'object')
  434.   {
  435.     this._sPageType = pagetype.content;
  436.     if (this._sPageType)
  437.     {
  438.       this._bRefTopic = this._oRegRef.test(this._sPageType);
  439.     }
  440.   }
  441. }
  442.  
  443. // returns a reference to a CPageData instance
  444. function EnsurePageData()
  445. {
  446.   if (!EnsurePageData._data)
  447.   {
  448.     EnsurePageData._data = new CPageData();
  449.   }
  450.   var oPD = EnsurePageData._data;
  451.  
  452.   return oPD;
  453. }
  454.  
  455. // retrieves the name of the topic from the metadata
  456. CPageData.prototype.GetTopicName = function()
  457. {
  458.   return this._sTopicName;
  459. }
  460.  
  461. // retrieves the persistent name of the topic from the metadata
  462. CPageData.prototype.GetPersistentName = function()
  463. {
  464.   return this._sPN;
  465. }
  466.  
  467. // indicates whether or not the topic is a ref topic
  468. CPageData.prototype.IsRefTopic = function()
  469. {
  470.   return this._bRefTopic;
  471. }
  472.  
  473. // indicates whether or not the topic is a ref topic
  474. CPageData.prototype.GetTopicLocation = function()
  475. {
  476.   return this._sLocation;
  477. }
  478.  
  479. // return whether or not this code is currently running on Win2000
  480. function IsWin2000()
  481. {
  482.   var sPlatVer;
  483.   return ((oBD.platform == "NT") && (sPlatVer = oBD.platVer) && (parseInt(sPlatVer) >= 5));
  484. }
  485.  
  486. // Add product/platform specific features based on information from _topicdata.  SetTopicData is called if oBD.majorVer is greater than 5 and _topicdata exists (DOM and XMLDOM members are employed).
  487. // IE#95215: For Mill B2 add IE5.5 splat based on information cached in _topicdata data island
  488. function SetTopicData(){
  489.   var oDocument=window.document;
  490.   var sProject=_topicdata.getAttribute("proj");
  491.   // add splat icon for new reference pages where the project is workshop, and the product is IE
  492.   if((sProject) && (sProject == "workshop"))
  493.   {
  494.     var aH1 = null;
  495.     var oPD = null;
  496.     var oIMG = null;
  497.     var sTPath = "";
  498.     var sAtt = "";
  499.     var sStd = "";
  500.     var sImg = "";
  501.  
  502.     var oProductIE=_topicdata.XMLDocument.selectSingleNode("/root/product[@rid='prod:IE']/@minver");
  503.     if(oProductIE)
  504.     {
  505.       var iMinVer=parseFloat(oProductIE.value);
  506.       if(iMinVer==5.5)
  507.       {
  508.         aH1=oDocument.body.getElementsByTagName("H1");
  509.         if(aH1.length)
  510.         {
  511.           oPD = EnsurePageData();
  512.           sTPath = oPD.GetTopicLocation();
  513.           oIMG=oDocument.createElement("<IMG SRC='" + MakeRelative(sTPath, "/workshop/graphics/new55.gif") + "' ALT='This feature is new for Internet Explorer 5.5.' ALIGN='middle' HEIGHT='10' WIDTH='40'>");
  514.           aH1[0].appendChild(oIMG);
  515.         }
  516.       }
  517.     }
  518.  
  519. /* Standards glyph showing is not done for now.  Uncomment this code to turn them on. //at
  520.     var sAtt=_topicdata.getAttribute("standard");
  521.     if(sAtt)
  522.     {
  523.       aH1=oDocument.body.getElementsByTagName("H1");
  524.       if(aH1.length)
  525.       {
  526.         oPD = EnsurePageData();
  527.         sTPath = oPD.GetTopicLocation();
  528.         sStd = sAtt.toLowerCase();
  529.  
  530.         if (sStd.indexOf("css1")>-1)
  531.         {
  532.           sImg = "<IMG SRC='" + MakeRelative(sTPath, "/workshop/graphics/std_css1.gif") + "' ALT='CSS1' ALIGN='top' HSPACE='5'>";
  533.         }
  534.         else if (sStd.indexOf("css2")>-1)
  535.         {
  536.           sImg = "<IMG SRC='" + MakeRelative(sTPath, "/workshop/graphics/std_css2.gif") + "' ALT='CSS2' ALIGN='top' HSPACE='5'>";
  537.         }
  538.         else if (sStd.indexOf("css3")>-1)
  539.         {
  540.           sImg = "<IMG SRC='" + MakeRelative(sTPath, "/workshop/graphics/std_css3.gif") + "' ALT='CSS3' ALIGN='top' HSPACE='5'>";
  541.         }
  542.         else if (sStd.indexOf("dom1")>-1)
  543.         {
  544.           sImg = "<IMG SRC='" + MakeRelative(sTPath, "/workshop/graphics/std_dom1.gif") + "' ALT='DOM1' ALIGN='top' HSPACE='5'>";
  545.         }
  546.         else if (sStd.indexOf("dom2")>-1)
  547.         {
  548.           sImg = "<IMG SRC='" + MakeRelative(sTPath, "/workshop/graphics/std_dom2.gif") + "' ALT='DOM2' ALIGN='top' HSPACE='5'>";
  549.         }
  550.         else if (sStd.indexOf("html32")>-1)
  551.         {
  552.           sImg = "<IMG SRC='" + MakeRelative(sTPath, "/workshop/graphics/std_html32.gif") + "' ALT='HTML 3.2' ALIGN='top' HSPACE='5'>";
  553.         }
  554.         else if (sStd.indexOf("html40")>-1)
  555.         {
  556.           sImg = "<IMG SRC='" + MakeRelative(sTPath, "/workshop/graphics/std_html40.gif") + "' ALT='HTML 4.0' ALIGN='top' HSPACE='5'>";
  557.         }
  558.  
  559.         if (sImg)
  560.         {
  561.           oIMG=oDocument.createElement(sImg);
  562.           aH1[0].appendChild(oIMG);
  563.         }
  564.       }
  565.     }
  566.     // Standards glyph showing.
  567.     */
  568.   }
  569. }
  570.  
  571. // Walk the images collection and turn install icons into show me buttons
  572. // IE#94569: For Mill B2 rip Showmes when UA is running on Win2000 and sample requires IE 5.5 or later
  573. function SetShowMes()
  574. {
  575.   var oImages = document.images;
  576.   var aContainers = new Array();
  577.  
  578.   // collect references to DIVs that contain qualifying IMGs
  579.   for (i = oImages.length-1; i >= 0 ; i--)
  580.   {
  581.     var oImg = oImages[i];
  582.     var fMinVer = parseFloat(oImg.getAttribute('MINVER', 1));
  583.     if (!fMinVer ||
  584.       (!oImg.getAttribute('SAMPLEPATH', 1)) ||
  585.       (oImg.parentElement.tagName != "A") ||
  586.       (oImg.src.lastIndexOf("ieget_animated.gif") == -1) ||
  587.       (oImg.parentElement.parentElement.tagName != "DIV") ||
  588.       (oImg.parentElement.parentElement.children(0).tagName != "DIV")
  589.       )
  590.     {
  591.       continue; // not a showme
  592.     }
  593.     else if (oBD.fullVer < fMinVer)
  594.     {
  595.       continue;
  596.     }
  597.     else
  598.     {
  599.       aContainers[aContainers.length] = oImg.parentElement.parentElement;
  600.     }
  601.   }
  602.  
  603.   var sShowMeClass = "clsShowme";
  604.   if (oBD.majorVer >= 5)
  605.   {
  606.     sShowMeClass += "5";
  607.   }
  608.  
  609.   // walk the containing DIVs
  610.   for (i = 0; i < aContainers.length; i++)
  611.   {
  612.     var oCntr = aContainers[i];
  613.     var bNewGifPresent = false;
  614.  
  615.     // gather data
  616.     var sToolTip, sClickCode;
  617.     var oImg = oCntr.children(1).children(0);
  618.     if (!oImg || !oImg.src || oImg.src.indexOf("ieget_animated.gif") == -1)
  619.     {
  620.         bNewGifPresent = true;
  621.         oImg = oCntr.children(3).children(0);
  622.     }
  623.  
  624.     var sSamplePath = oImg.SAMPLEPATH;
  625.     sToolTip = (!oImg.getAttribute('SAMPLETEXT', 1) ? "Click here to see a demonstration of this technology." : oImg.SAMPLETEXT);
  626.  
  627.     var oReg = new RegExp("^direct$", "i");
  628.     if (sSamplePath.match(oReg))
  629.     {
  630.       sClickCode = oImg.getAttribute('CODE', 1);
  631.     }
  632.     else
  633.     {
  634.       sClickCode = "window.open(\'" + sSamplePath + "\'" + (oImg.getAttribute('FEATURES', 1) ? ", null, \'" + oImg.FEATURES + "\'" : "") + ")";
  635.     }
  636.  
  637.     // change the innerHTML of the containing DIV to a BUTTON
  638.     // BUGBUG: Removed CLASS="clsShowme" to SPAN per 22222
  639.     oCntr.innerHTML = "";
  640.  
  641.     if (bNewGifPresent)
  642.         oCntr.innerHTML += '<IMG src="' + gsGraphicsPath + 'new.gif"> ';
  643.  
  644.     oCntr.innerHTML += '<BUTTON CLASS="' + sShowMeClass + '" TITLE="' + sToolTip + '" onclick="' + sClickCode + '"><SPAN>Show Me</SPAN></BUTTON>';
  645.   }
  646. }
  647.  
  648. // Compose a path to the specified destination path relative to the specified container path
  649. // The composition is performed case insensitively
  650. function MakeRelative(sContainer, sDestPath)
  651. {
  652.   // c:/sitebuilder/workshop/author/dhtml/reference/properties.htm
  653.   //   /sitebuilder/shared/css/ie4-wks.css
  654.   //   ../../../../shared/css/ie4-wks.css
  655.  
  656.   // c:/sitebuilder/workshop/author/dhtml/reference/properties.htm
  657.   //               /workshop/author/dhtml/reference/properties/accessKey.htm
  658.   //                                                properties/accessKey.htm
  659.  
  660.   // c:/sitebuilder/workshop/author/dhtml/reference/properties.htm
  661.   //               /workshop/code/common.js
  662.   //               ../../../code/common.js
  663.  
  664.   var oRegBS = new RegExp("\\\\", "g");
  665.   sContainer = sContainer.replace(oRegBS, "/");
  666.   sDestPath = sDestPath.replace(oRegBS, "/");
  667.  
  668.   var oRegHTTP = new RegExp("^http:\/\/", "i");
  669.   if (oRegHTTP.test(sDestPath))
  670.   {
  671.     return sDestPath;
  672.   }
  673.  
  674.   // BUGBUG: make sure topics are on the same drive/protocol/server
  675.   // IE peculiarity: In local path case, drive letter is preceded by forward slash
  676.   var oRegNoProtocol = new RegExp("^(file:\/\/\/)?\/?([a-zA-z]):", "i");
  677.   sContainer = sContainer.replace(oRegNoProtocol, "");
  678.   sDestPath = sDestPath.replace(oRegNoProtocol, "");
  679.  
  680.   var oRegBeginFS = new RegExp("^\/");
  681.   sDestPath = sDestPath.replace(oRegBeginFS, ""); // lop leading slash to eliminate empty first array element after split
  682.  
  683.   var oRegFS = new RegExp("\/");
  684.   var aSrc = sContainer.split(oRegFS);
  685.   aSrc.length -= 1; // lop off the filename from the container (assume container is a reference to a file)
  686.  
  687.   var oRegTS = new RegExp("\/$");
  688.   var bTrailingSlash = (oRegTS.test(sDestPath)); // preserve trailing slash
  689.   var aDest = sDestPath.split(oRegFS);
  690.  
  691.   var iSrcLen = aSrc.length, iDestLen = aDest.length;
  692.   var iSrcIndex = 0, iDestIndex = 0, iNoMatch = 0;
  693.  
  694.   // walk forward looking for matching portion of path
  695.   var bMatched = 0;
  696.   for (iSrcIndex = 0; iSrcIndex < iSrcLen; iSrcIndex++)
  697.   {
  698.     if (aSrc[iSrcIndex].toLowerCase() != aDest[iDestIndex].toLowerCase())
  699.     {
  700.       iNoMatch++;
  701.     }
  702.     else
  703.     {
  704.       bMatched =  1;
  705.       break;
  706.     }
  707.   }
  708.  
  709.   if (bMatched)
  710.   {
  711.  
  712.     var aRelPath = new Array();
  713.  
  714.     while (iSrcIndex < iSrcLen && iDestIndex < iDestLen && aSrc[iSrcIndex].toLowerCase() == aDest[iDestIndex].toLowerCase())
  715.     {
  716.       iSrcIndex++; iDestIndex++;
  717.     }
  718.  
  719.     // tack remaining portion of destination path onto the end of the result
  720.     while (iDestIndex < iDestLen)
  721.     {
  722.       aRelPath[aRelPath.length] = aDest[iDestIndex];
  723.       iDestIndex++;
  724.     }
  725.  
  726.     var sRelPath = aRelPath.join('/');
  727.  
  728.     // climb out of what remains of the source (excluding the filename)
  729.     while (iSrcIndex < iSrcLen)
  730.     {
  731.       sRelPath = "../" + sRelPath;
  732.       iSrcIndex++;
  733.     }
  734.  
  735.     return sRelPath + (bTrailingSlash ? "/" : "");
  736.   }
  737.   else // BUGBUG: no overlap, so just return what was passed in?
  738.   {
  739.     return sDestPath;
  740.   }
  741. }
  742.  
  743.  
  744. // Function that adds the "view-source:" prefix to the specified vroot
  745. // View-source syntax:
  746. //    view-source:http://sitebuilder.microsoft.com/workshop/ul.sct
  747. //
  748. // Note that view-source only takes an absolute path, and thus the function below
  749. // does the munging of the protocol + host to the vroot, resulting in an absolute path.
  750. //
  751. // Sample Usage:
  752. //    <A HREF="javascript:HandleViewSource('/workshop/samples/components/scriptoid/calc/engine.sct')">engine.sct</A>
  753. function HandleViewSource(sURL)
  754. {
  755.    location.href = "view-source:" + location.protocol + "//" + location.host + sURL;
  756. }
  757.  
  758. // Generate an ID unique to the page
  759. function GenerateID(sPrefix)
  760. {
  761.   if ("MSIE" == oBD.browser && oBD.majorVer >= 5)
  762.   {
  763.     return (sPrefix ? sPrefix : '') + document.uniqueID;
  764.   }
  765.   else
  766.   {
  767.     for (iTry = 0; iTry < 3; iTry++)
  768.     {
  769.       var sUniqueID = (sPrefix ? sPrefix : '') + Math.round(Math.random()*100000000);
  770.       if (document.all(sUniqueID) == null) // verify that the ID is not already in use
  771.       {
  772.         return sUniqueID;
  773.       }
  774.     }
  775.   }
  776.   return null;
  777. }
  778.  
  779. // Add client caps to the specified element on the page
  780. // returns the element to which the behavior was added
  781. // oElem - optional. The element to which the behavior was added (BODY is the default)
  782. function EnableClientCaps(oElem)
  783. {
  784.   if (!oBD.getsNavBar || oBD.majorVer < 5) // new for IE5
  785.   {
  786.     return null;
  787.   }
  788.  
  789.   if (typeof(EnableClientCaps.oCaps) == 'object') // already cached? return it
  790.   {
  791.     return EnableClientCaps.oCaps;
  792.   }
  793.  
  794.   if (typeof(oElem) != 'object') // validate params
  795.   {
  796.     oElem = document.body;
  797.   }
  798.  
  799.   // addBehavior came in IE5 B2, so check a B2 property before making call
  800.   if (typeof(oElem.behaviorUrns) != 'object')
  801.   {
  802.     return null;
  803.   }
  804.  
  805.   /* var iBehaviorID = */ oElem.addBehavior("#default#clientcaps");
  806.  
  807.   if (typeof(oElem.platform) == 'string')
  808.   {
  809.     EnableClientCaps.oCaps = oElem;
  810.     return oElem;
  811.   }
  812.   else
  813.   {
  814.     EnableClientCaps.oCaps = null;
  815.     return null;
  816.   }
  817. }
  818.  
  819. function toggle(oElement)
  820. {
  821.     if (!oElement)
  822.         oElement=event.srcElement;
  823.     s=oElement.ShowHideType;
  824.     var SpanIndex=oElement.sourceIndex;
  825.     var oPre=document.all.item(SpanIndex+1);
  826.     var o=oPre;
  827.     var oDiv=oPre;
  828.       o=o.nextSibling
  829.     if (o && o.nodeName=="DIV")
  830.     {
  831.         oDiv=o;
  832.     }
  833.  
  834.     var oFC = oDiv.all.item(0);
  835.     if (oPre.style.display=="none")
  836.     {
  837.         oPre.style.display="block";
  838.         if( oFC && (oFC.tagName == "BUTTON" || oFC.className == "clsShowMe") )
  839.             oDiv.style.display="block";
  840.         oElement.innerText="Hide " + s;
  841.     }
  842.     else
  843.     {
  844.         oPre.style.display="none";        
  845.         if( oFC && (oFC.tagName == "BUTTON" || oFC.className == "clsShowMe") )
  846.             oDiv.style.display="none";
  847.         oElement.innerText="Show " + s;
  848.     }
  849. }
  850.  
  851. function hideExamples()
  852. {
  853.     var colPre=document.all.tags("PRE");
  854.     for (var i=0;i<colPre.length;i++)
  855.     {
  856.         if (colPre.item(i).className=="clsCode")
  857.         {
  858.             if (colPre.item(i).offsetHeight > 200)
  859.             {
  860.                 var oSpan=document.createElement("P");            
  861.                 colPre.item(i).parentNode.insertBefore(oSpan,colPre.item(i));
  862.                 oSpan.onclick=toggle;
  863.                 oSpan.ShowHideType="Example"
  864.                 oSpan.style.textDecorationUnderline=true;
  865.                 oSpan.style.fontWeight="bold";
  866.                 oSpan.style.cursor="hand";
  867.                 // Code decoration (IE 5 only) will hide the example
  868.                 if ( oBD.majorVer < 5 )
  869.                 {
  870.                     toggle(oSpan);
  871.                 }
  872.             }
  873.         }
  874.     }        
  875. }
  876.  
  877. function ViewSource(sSelectId)
  878. {
  879.   var sUrl = document.location.href;
  880.   var sExt = sUrl.substring(sUrl.lastIndexOf("."));
  881.   var oFile = document.all.item(sSelectId);
  882.   if (oFile == null || oFile.value == "")
  883.   {
  884.     alert("No file selected.");
  885.   }
  886.   else
  887.   {
  888.       var sSrc = document.all.item(sSelectId).value + sExt;
  889.     window.open(sSrc, "Window", "width=800,height=555,resizable=no, scrollbars=yes");
  890.   }
  891. }